package n93_Fork_Join线程池;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

import static utils.Sleeper.sleep;

/**
 * @author fu
 * @date 2022-04-07 21:57
 * 概要：
 *  ---------------------------------------------------------------
 * |                                                              |
 * |    Fork/Join 分治思想，适用于能够进行 任务拆分的 CPU密集型运算     |
 * |                                                             |
 * |=============================================================
 */
@Slf4j(topic = "c.T1")
public class T2_test_ForkJoin_改进_并行 {

    public static void main(String[] args) {
        // 1. 创建线程池对象
        final ForkJoinPool pool = new ForkJoinPool(4); // 如果 无参 就是使用CPU核心数为 线程池线程数量

        final Integer res = pool.invoke(new MyTbsk(1, 5));

        System.out.println(res);
    }
}

/**
 * 1~n 之间的整数求和 ------ 用 [递归]
 *  有返回值 继承 RecursiveTask
 *  没返回值 继承 RecursiveAction
 */
@Slf4j(topic = "c.MT")
class MyTbsk extends RecursiveTask<Integer>{

    private int begin;
    private int end;

    public MyTbsk(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    protected Integer compute() {

//        sleep(1);// ------------------------ 进入 等待 --------------------------
        // 终止条件
        //   相等就是同一个数，返回本身就行
        if (begin == end) {
            log.debug("join() {}", begin);
            return begin;
        }
        //   相邻两个数 直接返回和
        if (end - begin == 1) {
            log.debug("join() {} + {} = {}", begin, end, end + begin);
            return end + begin;
        }


        // 取中间值
        int mid = (end + begin)/2;

        // 多拆几个任务
        MyTbsk t1 = new MyTbsk(begin, mid);
        t1.fork();
        MyTbsk t2 = new MyTbsk(mid+1, end);
        t2.fork();

        log.debug("fork() {} + {} = ?", t1, t2);

        // 结果 - [阻塞等待 下面拆分任务的执行结果]
        int result = t1.join() + t2.join();
        log.debug("join() {} + {} = {}", t1, t2, result);

        return result;
    }

    @Override
    public String toString() {
        return "{" + begin + ", " + end + "}";
    }
}








